package com.yanyeori.framework.security.filter;

import com.yanyeori.framework.core.constant.BaseWebCodeEnum;
import com.yanyeori.framework.core.model.WebResponse;
import com.yanyeori.framework.core.util.HttpUtil;
import com.yanyeori.framework.core.util.ServletUtil;
import com.yanyeori.framework.security.bo.UserDetail;
import com.yanyeori.framework.security.constant.SecurityConst;
import com.yanyeori.framework.security.service.PermissionsService;
import com.yanyeori.framework.security.service.RateLimiterService;
import com.yanyeori.framework.security.util.SecurityUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.web.filter.OncePerRequestFilter;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * Authentication认证成功之后的filter
 *
 * @author chenkuan 2020/12/5
 */
@Slf4j
public class AuthSuccessAfterFilter extends OncePerRequestFilter {

    private final RateLimiterService rateLimiterService;
    private final PermissionsService permissionsService;

    public AuthSuccessAfterFilter(RateLimiterService rateLimiterService, PermissionsService permissionsService) {
        this.rateLimiterService = rateLimiterService;
        this.permissionsService = permissionsService;
    }

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException, ServletException {
        //请求ip地址
        String requestIp = HttpUtil.getClientIP(request);
        //访问的servletPath
        String servletPath = SecurityUtil.getServletPath(request);
        //Security.Authentication
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();

        //校验Security是否已认证
        if (authentication == null || !authentication.isAuthenticated()) {
            //未认证状态，不作处理
            chain.doFilter(request, response);
            return;
        }

        //限流访问
        WebResponse<?> webResponse = rateLimiterService.validLimiterService(requestIp, servletPath);
        if (!webResponse.isSuccess()) {
            log.info("IP [{}], url [{}] access restricted", requestIp, servletPath);
            ServletUtil.writeToResponse(response, BaseWebCodeEnum.OK.code(), webResponse);
            return;
        }

        //处理匿名接口
        if (authentication.isAuthenticated() && SecurityConst.ANONYMOUS_PRINCIPAL.equals(authentication.getPrincipal())
                && (authentication.getAuthorities() != null && authentication.getAuthorities().iterator().hasNext() && SecurityConst.ROLE_ANONYMOUS.equals(authentication.getAuthorities().iterator().next().getAuthority()))) {
            chain.doFilter(request, response);
            return;
        }

        //UserDetail
        UserDetail userDetail = (UserDetail) authentication.getPrincipal();

        //接口访问权限校验
        webResponse = permissionsService.validUserInterfacePer(userDetail, servletPath);
        if (!webResponse.isSuccess()) {
            log.info("User [{}] does not have permission to access url [{}]", userDetail.getUsername(), servletPath);
            ServletUtil.writeToResponse(response, BaseWebCodeEnum.OK.code(), webResponse);
            return;
        }

        //扩展自定义过滤器
        webResponse = FilterHandler.handle(request, response, userDetail);
        if (!webResponse.isSuccess()) {
            log.warn("Request filter validation failed: {}", webResponse.getMessage());
            ServletUtil.writeToResponse(response, BaseWebCodeEnum.OK.code(), webResponse);
            return;
        }

        chain.doFilter(request, response);
    }
}
